package com.csun.cmny.provider.utils;

import com.csun.cmny.provider.model.constant.EmpConstant;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2018-12-15 11:10
 * @Description: 身份证信息工具类
 */
public class IdCardUtil {

    /**
     * 根据身份证的号码算出当前身份证持有者的性别和年龄 18位身份证
     *
     * @return
     * @throws Exception
     */
    public static Map<String, Object> getCarInfo(String CardCode)
            throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        String year = CardCode.substring(6).substring(0, 4);    // 得到年份
        String yue = CardCode.substring(10).substring(0, 2);    // 得到月份
        String day = CardCode.substring(12).substring(0,2);     // 得到日
        Integer sex = 0;
        if (Integer.parseInt(CardCode.substring(16).substring(0, 1)) % 2 == 0) {    // 判断性别
            sex = 0;
        } else {
            sex = 1;
        }
        Date date = new Date();// 得到当前的系统时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String fyear = format.format(date).substring(0, 4); // 当前年份
        String fyue = format.format(date).substring(5, 7);  // 月份
        String fday = format.format(date).substring(8,10);
        int age = 0;
        if (Integer.parseInt(yue) <= Integer.parseInt(fyue)) {  // 当前月份大于用户出身的月份表示已过生
            age = Integer.parseInt(fyear) - Integer.parseInt(year) + 1;
        } else {// 当前用户还没过生
            age = Integer.parseInt(fyear) - Integer.parseInt(year);
        }
        String birthday = year + "-" + yue + "-" + day;

        map.put("sex", sex);
        map.put("age", age);
        map.put("birthday", birthday);

        return map;
    }

    /**
     * 15位身份证的验证
     *
     * @param
     * @throws Exception
     */
    public static Map<String, Object> getCarInfo15W(String card)
            throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        String uyear = "19" + card.substring(6, 8); // 年份
        String uyue = card.substring(8, 10);        // 月份
        String uday = card.substring(10, 12);       //日
        String usex = card.substring(14, 15);       // 用户的性别
        Integer sex = 0;
        if (Integer.parseInt(usex) % 2 == 0) {
            sex = 0;
        } else {
            sex = 1;
        }
        Date date = new Date(); // 得到当前的系统时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String fyear = format.format(date).substring(0, 4); // 当前年份
        String fyue = format.format(date).substring(5, 7);  // 月份
        String fday=format.format(date).substring(8,10);
        int age = 0;
        if (Integer.parseInt(uyue) <= Integer.parseInt(fyue)) {     // 当前月份大于用户出身的月份表示已过生
            age = Integer.parseInt(fyear) - Integer.parseInt(uyear) + 1;
        } else {    // 当前用户还没过生
            age = Integer.parseInt(fyear) - Integer.parseInt(uyear);
        }
        String birthday = uyear + "-" + uyue + "-" + uday;

        map.put("sex", sex);
        map.put("age", age);
        map.put("birthday", birthday);

        return map;
    }

    /**
     * 校验身份证号码
     *
     * <p>
     * 适用于18位的二代身份证号码
     * </p>
     *
     * @param IDNo18 身份证号码
     * @return true - 校验通过<br>
     *         false - 校验不通过
     * @throws IllegalArgumentException
     *             如果身份证号码为空或长度不为18位或不满足身份证号码组成规则
     *             <i>6位地址码+
     *             出生年月日YYYYMMDD+3位顺序码
     *             +0~9或X(x)校验码</i>
     */
    public static boolean checkIDNo(String IDNo18) {
        // 校验身份证号码的长度
        if (!checkStrLength(IDNo18, 18)) {
            throw new IllegalArgumentException();
        }
        // 匹配身份证号码的正则表达式
        if (!regexMatch(IDNo18, EmpConstant.REGEX_ID_NO_18)) {
            throw new IllegalArgumentException();
        }
        // 校验身份证号码的验证码
        return validateCheckNumber(IDNo18);
    }

    /**
     * 校验字符串长度
     *
     * @param inputString 字符串
     * @param len 预期长度
     * @return true - 校验通过<br>
     *         false - 校验不通过
     */
    private static boolean checkStrLength(String inputString, int len) {
        if (inputString == null || inputString.length() != len) {
            return false;
        }
        return true;
    }

    /**
     * 匹配正则表达式
     *
     * @param inputString 字符串
     * @param regex 正则表达式
     * @return true - 校验通过<br>
     *         false - 校验不通过
     */
    private static boolean regexMatch(String inputString, String regex) {
        return inputString.matches(regex);
    }

    /**
     * 校验码校验
     * <p>
     * 适用于18位的二代身份证号码
     * </p>
     *
     * @param IDNo18 身份证号码
     * @return true - 校验通过<br>
     *         false - 校验不通过
     */
    private static boolean validateCheckNumber(String IDNo18) {
        // 加权因子
        int[] W = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
        char[] IDNoArray = IDNo18.toCharArray();
        int sum = 0;
        for (int i = 0; i < W.length; i++) {
            sum += Integer.parseInt(String.valueOf(IDNoArray[i])) * W[i];
        }
        // 校验位是X，则表示10
        if (IDNoArray[17] == 'X' || IDNoArray[17] == 'x') {
            sum += 10;
        } else {
            sum += Integer.parseInt(String.valueOf(IDNoArray[17]));
        }
        // 如果除11模1，则校验通过
        return sum % 11 == 1;
    }

    /**
     * 计算身份证号码的校验码
     * <p>
     * 适用于18位的二代身份证号码，身份证号码由17位本体码和1位校验码组成
     * </p>
     *
     * @param masterNumber 本体码
     * @return 身份证号码
     * @throws IllegalArgumentException
     *             如果本体码为空或长度不为17位或不满足本体码组成规则
     *             <i>6位地址码+
     *             出生年月日YYYYMMDD+3位顺序码</i>
     */
    public static String computeIDNoCheckNumber(String masterNumber) {
        // 校验本体码的长度
        if (!checkStrLength(masterNumber, 17)) {
            throw new IllegalArgumentException();
        }
        // 匹配本体码的正则表达式
//        if (!regexMatch(masterNumber, REGEX_MASTER_NUMBER)) {
//            throw new IllegalArgumentException();
//        }
        // 计算校验码
        String checkNumber = computeCheckNumber(masterNumber);
        // 返回本体码+校验码=完整的身份证号码
        return masterNumber + checkNumber;
    }

    /**
     * 计算校验码
     * <p>
     * 适用于18位的二代身份证号码
     * </p>
     *
     * @param masterNumber 本体码
     * @return 校验码
     */
    private static String computeCheckNumber(String masterNumber) {
        // 加权因子
        int[] W = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
        char[] masterNumberArray = masterNumber.toCharArray();
        int sum = 0;
        for (int i = 0; i < W.length; i++) {
            sum += Integer.parseInt(String.valueOf(masterNumberArray[i])) * W[i];
        }
        // 根据同余定理得到的校验码数组
        String[] checkNumberArray = { "1", "0", "X", "9", "8", "7", "6", "5", "4",
                "3", "2" };
        // 得到校验码
        String checkNumber = checkNumberArray[sum % 11];
        // 返回校验码
        return checkNumber;
    }

    /**
     * 15位一代身份证号码升级18位二代身份证号码
     * <p>
     * 为15位的一代身份证号码增加年份的前2位和最后1位校验码
     * </p>
     *
     * @param IDNo15 15位的一代身份证号码
     * @return 18位的二代身份证号码
     */
    public static String updateIDNo15to18(String IDNo15) {
        // 校验身份证号码的长度
        if (!checkStrLength(IDNo15, 15)) {
            throw new IllegalArgumentException();
        }
        // 匹配身份证号码的正则表达式
        if (!regexMatch(IDNo15, EmpConstant.REGEX_ID_NO_15)) {
            throw new IllegalArgumentException();
        }
        // 得到本体码，因一代身份证皆为19XX年生人，年份中增加19，组成4位
        String masterNumber = IDNo15.substring(0, 6) + "19" + IDNo15.substring(6);
        // 计算校验码
        String checkNumber = computeCheckNumber(masterNumber);
        // 返回本体码+校验码=完整的身份证号码
        return masterNumber + checkNumber;
    }

}
